# encoding: utf-8
import xlrd
import os
import re
import shutil
import sys
import gzip
import math
import json
import hashlib


outputClientTsFilePath = ""

outputbinFilePath = ""


def walkDir(local_dir):
    # 保存所有文件的列表
    fileList = os.listdir(local_dir)  # 列出文件夹下所有的目录与文件
    global fileMd5Map

    for i in range(0, len(fileList)):
        filename = fileList[i]
        path = os.path.join(local_dir, filename)
        if os.path.isfile(path):
            fileStrArr = os.path.splitext(filename)
            if fileStrArr[0] == "enum":
                continue
            if (fileStrArr[1] == ".xlsx" or fileStrArr[1] == ".xlsm") and fileStrArr[0].find("~") == -1:

                fileMd5 = getFileMd5(path)
                if fileMd5Map.get(filename) == None or fileMd5 != fileMd5Map[filename]:
                    fileMd5Map[filename] =fileMd5
                    parseExcel(path, fileStrArr[0], 's')
                    parseExcel(path, fileStrArr[0], 'c')


            path = path.replace('\\', "/")
        elif os.path.isdir(path):
            pass
            # all_files.extend(__get_all_files_in_local_dir(path))

    outPutGzipFile()
    # write csv template
    writeClientCsvScript()
    writeServerCsvScript()
    copyData()
    saveMd5File()



def outPutGzipFile():
    clientfileList = os.listdir("../clientCsv")  # 列出文件夹下所有的目录与文件
    serverfileList = os.listdir("../serverCsv")
    global fileMd5Map
    clientCsvTextContent = ""
    serverCsvTextContent = ""
    for i in range(0, len(clientfileList)):
        filename = clientfileList[i]
        path = os.path.join("../clientCsv", filename)

        if os.path.isfile(path):
            fileStrArr = os.path.splitext(filename)
            if fileStrArr[1] == ".txt":
                f = open(path, "r",encoding="utf-8")
                clientCsvTextContent = clientCsvTextContent + f.read()
                f.close()
    for i in range(0, len(serverfileList)):
        filename = serverfileList[i]
        path = os.path.join("../serverCsv", filename)

        if os.path.isfile(path):
            fileStrArr = os.path.splitext(filename)
            if fileStrArr[1] == ".txt":
                f = open(path, "r",encoding="utf-8")
                serverCsvTextContent = serverCsvTextContent + f.read()
                f.close()

    fileList = os.listdir("../clientCsv")
    fileListJson = []
    clientPath = "../../Client/ZM/assets/"
    for i in range(0, len(fileList)):
        filename = fileList[i]
        fileListJson.append(filename.split(".")[0])
        shutil.copyfile("../clientCsv/" + filename,clientPath + "/resources/bin/" + filename)


    # outputFilePath = clientPath + "/resources/bin/bin.gz"
    # g = gzip.GzipFile(filename="", compresslevel=9, mode="wb", fileobj=open(outputFilePath, 'wb'))
    #
    jsonFile = open(clientPath + "/resources/bin/fileList.txt","w")
    jsonFile.write(json.dumps(fileListJson))
    jsonFile.close()
    # g.write(bytes(clientCsvTextContent, "utf-8"))
    # g.close()
    #
    f = open("../../Server/ZMServer/src/config.txt","w",encoding="utf-8")
    f.write(serverCsvTextContent)
    f.close()



def getFileMd5(filePath):
    file = open(filePath, 'rb')
    md5 = hashlib.md5(file.read()).hexdigest()
    file.close()
    return md5


def initMd5():
    global fileMd5Map
    if os.path.exists("../md5.json"):
        f = open("../md5.json")
        fileMd5Map = json.loads(f.read())
        f.close()


def saveMd5File():
    global fileMd5Map
    f = open("../md5.json", "w")
    f.write(json.dumps(fileMd5Map))
    f.close()





def writeClientCsvScript():
    binArrayFile = open("templates/csvTemplate.txt", "r")
    csvScriptContent = binArrayFile.read()
    binArrayFile.close()

    importStrs = ""
    loadStrs = ""

    fileList = os.listdir("../client")
    for i in range(0, len(fileList)):
        filename = fileList[i]
        fileStrArr = os.path.splitext(filename)
        if fileStrArr[0].find("cfg_") == -1:
            continue
        filename = str(fileStrArr[0]).replace("cfg_","")
        importStrs = importStrs + "import { %sConfig } from " % (filename.capitalize()) + '"./cfg_{}";\n'.format(
            filename)
        loadStrs = loadStrs + "{}Config.inst.localCsv();\n        ".format(filename.capitalize())
    csvScriptContent = csvScriptContent.replace("#1", importStrs)
    csvScriptContent = csvScriptContent.replace("#2", loadStrs)

    outPutClientCsvPath = outputClientTsFilePath + "csv.ts"

    writeFile(outPutClientCsvPath, csvScriptContent)
def writeServerCsvScript():
    binArrayFile = open("templates/csvTemplate.txt", "r")
    csvScriptContent = binArrayFile.read()
    binArrayFile.close()

    importStrs = ""
    loadStrs = ""
    fileList = os.listdir("../server")
    for i in range(0, len(fileList)):
        filename = fileList[i]
        fileStrArr = os.path.splitext(filename)
        if fileStrArr[0].find("cfg_") == -1:
            continue
        filename = fileStrArr[0].replace("cfg_","")
        importStrs = importStrs + "import { %sConfig } from " % (filename.capitalize()) + '"./cfg_{}";\n'.format(
            filename)
        loadStrs = loadStrs + "{}Config.inst.localCsv();\n        ".format(filename.capitalize())
    csvScriptContent = csvScriptContent.replace("#1", importStrs)
    csvScriptContent = csvScriptContent.replace("#2", loadStrs)

    writeFile("../server/csv.ts", csvScriptContent)



def haveBuildTypeInExcel(excelFilePath,buildType):
    isHave = False

    excelFile = xlrd.open_workbook(excelFilePath)
    sheet = excelFile.sheet_by_index(0)
    typeX = 0
    realX = 0
    while typeX < sheet.ncols:
        valueType = sheet.cell_value(2, typeX)
        kindType = sheet.cell_value(4,typeX)
        if buildType in kindType:
            isHave = True
            break
    return isHave

def parseExcel(excelFilePath, filename, buildType):
    global isJenkins
    csvFilePath = ""
    if buildType == "s":
        csvFilePath =  "../serverCsv/" + filename + ".txt"
    elif buildType == "c":
        csvFilePath = "../clientCsv/" + filename.lower() + ".txt"
    csvContent = ""
    if buildType == "s":
        csvContent = csvContent + "$$$$$" + filename.lower() + "\n"
    excelFile = xlrd.open_workbook(excelFilePath)
    sheet = excelFile.sheet_by_index(0)

    content = ""
    y = 6
    # 加入type
    typeX = 0
    realX = 0

    isHave = False
    while typeX < sheet.ncols:
        valueType = sheet.cell_value(2, typeX)
        kindType = sheet.cell_value(4,typeX)
        if buildType in kindType:
            isHave = True
            if valueType == " ":

                if (isJenkins):
                    sys.exit(1)
                else:
                    os.system("pause")
                continue
            if typeX < sheet.ncols - 1:
                content = content + sheet.cell_value(2, typeX) + "__"
            else:
                content = content + sheet.cell_value(2, typeX)
            realX += 1

        typeX += 1
    if content[len(content)-2:] == "__":
        content = content[0:len(content)-2]

    content = content + "\n"

    realX = 0
    while y < sheet.nrows:
        # cur y
        x = 0
        realX = 0
        paramContent = ""
        while x < sheet.ncols:
            valueType = sheet.cell_value(2, x)
            cellValue = sheet.cell_value(y, x)
            kindType = sheet.cell_value(4,x)
            if buildType in kindType:
                valueType = str(valueType).replace("\n", "")
                if valueType == "number":
                    if cellValue == "undefined" or cellValue == "null":
                        cellValue = -1
                    # cellValue = math.floor(int(cellValue))
                    cellValue = getNumberValue(cellValue)
                elif valueType == "string":
                    cellValue = cellValue = str(cellValue)
                    cellValue = cellValue.replace("\\n", "^")
                elif valueType == "boolean":
                    if cellValue == "true":
                        cellValue = 1
                    else:
                        cellValue = 0
                else:
                    originalCellValue = str(cellValue)
                    cellValue = str(cellValue)
                    cellValue = matchStr(cellValue,filename,y+1,x+1)
                    try:
                        json.loads(cellValue)
                    except:

                        print("[ERROR] 配置表 = {} 错误数据 = {} 第{}行 第{}列".format(filename, originalCellValue, y + 1, x + 1))
                        if (isJenkins):
                            sys.exit(1)
                        else:
                            os.system("pause")

                if x < sheet.ncols - 1:
                    paramContent += str(cellValue) + "__"
                else:
                    paramContent += str(cellValue)
                realX += 1

            x += 1
        if paramContent[len(paramContent) - 2:] == "__":
            paramContent = paramContent[0:len(paramContent) - 2]
        if y < sheet.nrows - 1:

            content += paramContent + "\n"
        else:
            content += paramContent
        y += 1

    csvContent = csvContent + content
    if buildType == "s":
        csvContent = csvContent + "\n ***************\n"
    csvContent = csvContent.replace("<h>","<color=#64ff27><outline color=#4a3229 width=2>")
    csvContent = csvContent.replace("</h>", "</outline></c>")
    csvContent = csvContent.replace("\xa0","")
    if isHave:
        outPutTs(sheet, filename, buildType)
        file = open(csvFilePath, "w",encoding="utf-8")
        file.write(csvContent)
        file.close()


def parseEnumFile():
    enumFilePath = os.path.abspath("..") + "/enum.xlsx"
    excelFile = xlrd.open_workbook(enumFilePath)
    sheet = excelFile.sheet_by_index(0)
    global enumDict
    curX = 0
    while curX < sheet.ncols:

        valueType = sheet.cell_value(0, curX + 1)
        parentKey = sheet.cell_value(0, curX)
        curY = 1
        if enumDict.get(parentKey) == None:
            enumDict[parentKey] = {}
        while curY < sheet.nrows:
            key = sheet.cell_value(curY, curX)
            value = sheet.cell_value(curY, curX + 1)

            curY += 1
            if value == "":
                continue
            if valueType == "number":
                value = str(math.floor(value))
            else:
                value = str(value)
            enumDict[parentKey][key] = value

        curX += 4


def outPutTs(sheet, filename,buildType):
    curX = 0
    if sheet.cell_value(1, 0) == "level":
        outPutNormalTs(sheet, filename,buildType)

        return
    while curX < sheet.ncols:
        valueName = sheet.cell_value(1, curX)
        if valueName == "level":
            outPutLevelTs(sheet, filename,buildType)
            return
        curX += 1
    outPutNormalTs(sheet, filename,buildType)


def outPutNormalTypeTs(sheet, filename,buildType):
    typeFileName = "type_{}.ts".format(filename)
    outPutClientTypeFilePath = "../client/" + typeFileName
    if buildType == "s":
        outPutClientTypeFilePath = "../server/" + typeFileName
    # 原始数据
    templateFile = open("templates/typeTemplate.txt", "r")
    typeContent = templateFile.read()
    templateFile.close()
    className = filename.capitalize()
    typeContent = typeContent.replace("$", className)

    curx = 0

    ParamsContent = ""
    realX = 0
    while curx < sheet.ncols:
        valueType = sheet.cell_value(2, curx)
        valueName = sheet.cell_value(1, curx)
        defaultValue = sheet.cell_value(3, curx)
        contentProperty = sheet.cell_value(4, curx)

        if buildType in contentProperty:
            if valueType == "number":
                defaultValue = 1
            elif valueType == "string":
                defaultValue = '"' + defaultValue + '"'
            param = "{}: {} = {};\n    ".format(valueName, valueType, defaultValue)
            ParamsContent += param
            realX += 1
        curx += 1
    clientContent = typeContent.replace("#1", ParamsContent)
    clientOrignal = getTypeOriginalContent(outPutClientTypeFilePath)
    clientContent = clientContent.replace("#2", clientOrignal)
    writeFile(outPutClientTypeFilePath, clientContent)


def getNumberValue(defaultNumber):
    if defaultNumber == "":
        defaultNumber = 0
    floatValue = str(defaultNumber)
    numberArr = floatValue.split(".")
    isFloatStr = len(numberArr) == 2
    isFloatNumber = False
    if isFloatStr:
        for c in numberArr[1]:
            if c != "0":
                isFloatNumber = True
                break
    else:
        return int(defaultNumber)
    if isFloatNumber:

        defaultNumber = round(defaultNumber, min(len(numberArr[1]), 3))
    else:
        defaultNumber = int(numberArr[0])

    return defaultNumber


def outPutLevelTypeTs(sheet, filename,buildType):
    # 原始数据
    typeFileName = "type_{}.ts".format(filename)
    outPutClientTypeFilePath = "../client/" + typeFileName
    if buildType == "s":
        outPutClientTypeFilePath = "../server/" + typeFileName

    # 原始数据
    templateFile = open("templates/typeLevelTemplate.txt", "r")
    typeContent = templateFile.read()
    templateFile.close()
    className = filename.capitalize()
    typeContent = typeContent.replace("$", className)

    curx = 0

    clientParamsContent = ""
    clientLevelParamsContent = ""
    levelIndex = -1
    realX = 0
    while curx < sheet.ncols:
        valueType = sheet.cell_value(2, curx)
        valueName = sheet.cell_value(1, curx)
        defaultValue = sheet.cell_value(3, curx)
        contentProperty = sheet.cell_value(4, curx)
        if buildType in contentProperty:
            if valueName == "level":
                levelIndex = curx
                # continue
            if valueType == "number":
                # print(defaultValue)
                defaultValue = getNumberValue(defaultValue)
            elif valueType == "string":
                defaultValue = '"' + defaultValue + '"'
            param = "{}: {} = {};\n    ".format(valueName, valueType, defaultValue)
            if levelIndex == -1:

                    clientParamsContent = clientParamsContent + param
            elif curx >= levelIndex and levelIndex != -1:
                    clientLevelParamsContent = clientLevelParamsContent + param
            realX+=1

        curx += 1
    clientContent = typeContent.replace("#1", clientParamsContent)
    clientContent = clientContent.replace("#2", clientLevelParamsContent)
    # client get customData
    clientOrignal = getTypeOriginalContent(outPutClientTypeFilePath)
    clientContent = clientContent.replace("#3", clientOrignal)
    writeFile(outPutClientTypeFilePath, clientContent)


def getTypeOriginalContent(filePath):
    originalContent = ""
    if os.path.exists(filePath):
        file = open(filePath, "r", encoding='utf-8')
        line = file.readline()

        index = 0
        lineIndex = -1
        isOrignalContent = False
        while line:
            line = file.readline()
            pattern = re.compile("[a-zA-Z0-9]")
            result = pattern.findall(line)

            isNoneStr = result == None

            if isNoneStr:
                line = ""
            if isOrignalContent and line != '\n':
                originalContent = originalContent + line
            if line == SEPARATOR:
                isOrignalContent = True
        return originalContent
        file.close()


    else:
        return originalContent


def outPutNormalTs(sheet, filename,buildType):
    clientContent = ""
    outPutNormalTypeTs(sheet, filename,buildType)
    global outputTsFilePath
    curX = 0
    # 读取模板
    templateFile = open("templates/buildTemplate.txt", "r", encoding='utf-8')
    templateContent = templateFile.read()
    templateFile.close()
    clientContent = templateContent.replace("$", filename.capitalize())
    clientContent = clientContent.replace("%", filename.lower())
    clientParam = ""
    levelIndex = -1
    realX = 0
    while curX < sheet.ncols:
        valueType = sheet.cell_value(2, curX)
        valueName = sheet.cell_value(1, curX)
        valueName = str(valueName).replace("?", "")
        valueProperty = sheet.cell_value(4, curX)

        if buildType in valueProperty:
            paramstr = "params[{}],\n"
            param = "                {}: ".format(valueName) + paramstr.format(realX)
            clientParam = clientParam + param
            realX +=1

        curX += 1
    clientContent = clientContent.replace("#1", clientParam)
    filename = "cfg_{}.ts".format(filename)

    outPutTypeFilePath = "../client/" + filename
    if buildType == "s":
        outPutTypeFilePath = "../server/" + filename
    writeFile(outPutTypeFilePath, clientContent)


def outPutLevelTs(sheet, filename,buildType):
    outPutLevelTypeTs(sheet, filename,buildType)
    global outputTsFilePath
    curX = 0
    # 读取模板
    templateFile = open("templates/levelTemplate.txt", "r", encoding='utf-8')
    templateContent = templateFile.read()
    templateFile.close()

    clientContent = templateContent.replace("$", filename.capitalize())
    clientContent = clientContent.replace("%", filename.lower())

    levelIndex = -1

    clientParams = ""
    levelDecodeStr = "  this.csvData[key].levels[params[{}]] ="
    realX = 0
    while curX < sheet.ncols:
        valueType = sheet.cell_value(2, curX)
        valueName = sheet.cell_value(1, curX)
        valueName = str(valueName).replace("?", "")
        valueProperty = sheet.cell_value(4, curX)

        if buildType in valueProperty:
            paramstr = "params[{}],\n"

            if valueName == "level":

                levelIndex = curX
                param = "                levels:{},\n"
                clientParams = clientParams + param
                levelDecodeStr = levelDecodeStr.format(realX) + '{\n'

            if levelIndex < curX and levelIndex == -1:
                param = "                {}: ".format(valueName) + paramstr.format(realX)
                clientParams = clientParams + param
            else:
                levelDecodeStr = levelDecodeStr + "              {}: ".format(valueName) + paramstr.format(realX)
            realX += 1
        if curX == sheet.ncols - 1:
            levelDecodeStr = levelDecodeStr + "        }"

        curX += 1
    clientContent = clientContent.replace("#1", clientParams)
    clientContent = clientContent.replace("#2", levelDecodeStr)

    filename = "cfg_{}.ts".format(filename)

    outPutClientTypeFilePath = "../client/" + filename
    if buildType == "s":
        outPutClientTypeFilePath = "../server/" + filename
    writeFile(outPutClientTypeFilePath, clientContent)


def writeFile(filepath, content):
    file = open(filepath, "w", encoding='utf-8')
    file.write(content)
    file.close()
    print("output file = {}".format(os.path.join(filepath)))



def copyData():
    clientPath = "../../Client/ZM/assets/"
    serverPath = "../../Server/ZMServer/src/app/configurations"
    copyDir("../client", clientPath + "Script/configurations")
    copyDir("../server", serverPath)


def copyDir(curDir, desDir):
    # if os.path.exists(desDir):
    #     shutil.rmtree(desDir)
    tempPath = os.path.abspath(desDir)
    print("copy ={} to={}".format(curDir, desDir))
    # shutil.copytree(curDir,desDir)
    fileList = os.listdir(curDir)  # 列出文件夹下所有的目录与文件
    for i in range(0, len(fileList)):
        filename = fileList[i]
        path = os.path.join(curDir, filename)
        if os.path.isfile(path):
            shutil.copy(path, tempPath)


if __name__ == '__main__':
    if (len(sys.argv) == 2):
        print("param = ", sys.argv[1])
        canCommit = sys.argv[1] == "commit"
    elif (len(sys.argv) == 3):
        canCommit = sys.argv[1] == "commit"
        print(sys.argv[2])
        isJenkins = sys.argv[2] == "jenkins"
    outputClientTsFilePath = os.path.abspath("../client") + "/"
    outputbinFilePath = os.path.abspath("../bin") + "/"
    excel_dir = os.path.abspath("..")
    initMd5()
    parseEnumFile()
    # print(excel_dir)
    walkDir(excel_dir)
